home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CreatingGames / Utilities / C / GBDK / lib / crt0.s < prev    next >
Encoding:
Text File  |  1996-04-03  |  14.4 KB  |  1,056 lines

  1.     .include    "lib/global.h"
  2.  
  3.     .refresh_OAM    =    0xFF80
  4.  
  5.     ; Main user routine
  6.     .globl    _main
  7.  
  8.     ; ****************************************
  9.     ; Beginning of module
  10.     .title    "GB Runtime"
  11.     .module    Runtime
  12.     .area    HEADER    (ABS)
  13.  
  14.     ; Standard header for the GB
  15.     .org    0x00
  16.  
  17.     ; IRQ vectors
  18.     .org    0x40
  19.     JP    0x60
  20.  
  21.     .org    0x48
  22.     RETI
  23.  
  24.     .org    0x50
  25.     RETI
  26.  
  27.     .org    0x58
  28.     RETI
  29.  
  30.     .org    0x60
  31.     PUSH AF
  32. ;      PUSH BC
  33. ;      PUSH DE
  34. ;      PUSH HL
  35.     CALL    .refresh_OAM
  36. ;      POP HL
  37. ;      POP DE
  38. ;      POP BC
  39.     POP AF
  40.     RETI
  41.  
  42.     ; GameBoy Header
  43.  
  44.     .org    0x100
  45.     ; Standard Nintendo DO NOT CHANGE...
  46.     NOP
  47.     JP    0x150
  48.     .byte    0xCE,0xED,0x66,0x66
  49.     .byte    0xCC,0x0D,0x00,0x0B
  50.     .byte    0x03,0x73,0x00,0x83
  51.     .byte    0x00,0x0C,0x00,0x0D
  52.     .byte    0x00,0x08,0x11,0x1F
  53.     .byte    0x88,0x89,0x00,0x0E
  54.     .byte    0xDC,0xCC,0x6E,0xE6
  55.     .byte    0xDD,0xDD,0xD9,0x99
  56.     .byte    0xBB,0xBB,0x67,0x63
  57.     .byte    0x6E,0x0E,0xEC,0xCC
  58.     .byte    0xDD,0xDC,0x99,0x9F
  59.     .byte    0xBB,0xB9,0x33,0x3E
  60.  
  61.     .org    0x134
  62.     ; Title of the game
  63.     .asciz    "Title"
  64.  
  65.     .org    0x144
  66.     ; Not used
  67.  
  68.     .org    0x147
  69.     ; Cartridge type is ROM only
  70.     .byte    0
  71.  
  72.     .org    0x148
  73.     ; ROM size is 32kB
  74.     .byte    0
  75.  
  76.     .org    0x149
  77.     ; RAM size is 0kB
  78.     .byte    0
  79.  
  80.     .org    0x14A
  81.     ; Maker ID
  82.     .byte    0x00,0x00
  83.  
  84.     .org    0x14C
  85.     ; Version number
  86.     .byte    0x01
  87.  
  88.     .org    0x14D
  89.     ; Complement check
  90.     .byte    0x00
  91.  
  92.     .org    0x14E
  93.     ; Checksum
  94.     .byte    0x00,0x00
  95.  
  96.     ; ****************************************
  97.     .org    0x150
  98.     ; Beginning of the code
  99.     DI            ; Disable interrupts
  100.     LD    SP,#0xCFFF    ; Initialize the stack
  101.     XOR    A        ; A = 0
  102.     LD    (.mode),A
  103.     LD    HL,#0xDFFF    ; Clear from 0xD000 to 0xDFFF
  104.     LD    C,#0x10
  105.     LD    B,#0x00
  106. 1$:
  107.     LD    (HL-),A
  108.     DEC    B
  109.     JR    NZ,1$
  110.     DEC    C
  111.     JR    NZ,1$
  112.     CALL    .clear_OAM
  113.                 ; Copy refresh_OAM routine to HIRAM
  114.     LD    C,#.refresh_OAM-0xFF00
  115.     LD    HL,#.start_refresh_OAM
  116.     LD    B,#.end_refresh_OAM-.start_refresh_OAM
  117. 2$:
  118.     LD    A,(HL+)
  119.     LDH    (C),A
  120.     INC    C
  121.     DEC    B
  122.     JR    NZ,2$
  123.     XOR    A        ; A = 0
  124.     LDH    (.SCROLLY),A
  125.     LDH    (.SCROLLX),A
  126.     LD    A,#0b10000000    ;    LCD        =    On
  127.                 ;    WindowBank    =    0x9800
  128.                 ;    Window        =    Off
  129.                 ;    BG Chr        =    0x8800
  130.                 ;    BG Bank        =    0x9800
  131.                 ;    OBJ        =    8x8
  132.                 ;    OBJ        =    Off
  133.                 ;    BG        =    Off
  134.     LDH    (.LCDCONT),A
  135.     CALL    .wait_vbl    ; Must be in VBL before turning the screen off.
  136.     LD    A,#0b00000011
  137.                 ;    LCD        =    Off
  138.                 ;    WindowBank    =    0x9800
  139.                 ;    Window        =    Off
  140.                 ;    BG Chr        =    0x8800
  141.                 ;    BG Bank        =    0x9800
  142.                 ;    OBJ        =    8x8
  143.                 ;    OBJ        =    On
  144.                 ;    BG        =    On
  145.     LDH    (.LCDCONT),A
  146.     CALL    .std_pal
  147.     LD    A,#0x01
  148.     LD    (0x2000),A    ; ROM bank 1
  149.     LD    A,#0x40
  150.     LDH    (.LCDSTAT),A
  151.     LD    A,#0b00000011
  152.                 ; Pin P10-P13    =    Off
  153.                 ; Serial I/O    =    Off
  154.                 ; Timer Ovfl    =    Off
  155.                 ; LCDC        =    On
  156.                 ; V-Blank    =    On
  157.     LDH    (.ISWITCH),A
  158.     XOR    A        ; A = 0
  159.     LDH    (.IFLAGS),A
  160.  
  161.     ; Call the main function
  162.     CALL    _main
  163.  
  164. 3$:
  165.     JR    3$        ; Wait forever
  166.  
  167.     .org    .MODE_TABLE
  168.     ; Jump table for modes
  169.     RET
  170.  
  171.     ; ****************************************
  172.  
  173.     ; Ordering of segments for the linker
  174.     .area    _CODE
  175.     .area    _DATA
  176.     .area    _LIT
  177.  
  178.     .area    _BSS
  179.  
  180.     ; We should be at address 0xC000
  181. .OAM:                ; DMA transfer must start at multiples of 0x100
  182.     .ds    0xA0
  183.  
  184. .mode:
  185.     .ds    0x01
  186.  
  187.     ; Runtime library
  188.     .area    _CODE
  189.  
  190.     ; Shift HL left arithmetically by DE
  191. .asl::
  192. .lsl::
  193.     LD    A,D
  194.     OR    E
  195.     RET    Z
  196.     PUSH    DE
  197. 1$:
  198.     ADD    HL,HL
  199.     DEC    DE
  200.     LD    A,D
  201.     OR    E
  202.     JR    NZ,1$
  203.     POP    DE
  204.     RET
  205.  
  206.     ; Shift HL right arithmetically by DE
  207. .asr::
  208.     LD    A,D
  209.     OR    E
  210.     RET    Z
  211.     PUSH    DE
  212. 1$:
  213.     SRA    H        ; Shift right
  214.     RR    L
  215.     DEC    DE
  216.     LD    A,D
  217.     OR    E
  218.     JR    NZ,1$
  219.     POP    DE
  220.     RET
  221.  
  222.     ; Shift HL right logically by DE
  223. .lsr::
  224.     LD    A,D
  225.     OR    E
  226.     RET    Z
  227.     PUSH    DE
  228. 1$:
  229.     SRL    H        ; Shift right
  230.     RR    L
  231.     DEC    DE
  232.     LD    A,D
  233.     OR    E
  234.     JR    NZ,1$
  235.     POP    DE
  236.     RET
  237.  
  238.     ; HL = DE * HL [signed]
  239. .mul::
  240. .mulu::
  241.     PUSH    BC
  242.     LD    B,H
  243.     LD    C,L
  244.     LD    HL,#0x00
  245. 1$:
  246.     LD    A,C
  247.     RRCA
  248.     JR    NC,2$
  249.     ADD    HL,DE
  250. 2$:
  251.     SRL    B
  252.     RR    C
  253.     LD    A,C
  254.     OR    B
  255.     JR    Z,3$
  256.     SLA    E
  257.     RL    D
  258.     LD    A,D
  259.     OR    E
  260.     JR    NZ,1$
  261. 3$:
  262.     POP    BC
  263.     RET
  264.  
  265. ; 16-bit x 16-bit Division Subroutine
  266. ;
  267. ; This subroutine divides the 16-bit quantity in register
  268. ; pair DE by the 16-bit quantity in register pair BC.
  269. ; The result will be stored in register pair DE and the
  270. ; remainder in register pair BC.
  271.  
  272. ; * Ram memory variables *
  273.  
  274.     .area    _BSS
  275.  
  276. .divsgn:
  277.     .ds    0x01
  278.  
  279. .divtmp:
  280.     .ds    0x02
  281.  
  282. .divcnt:
  283.     .ds    0x01
  284.  
  285.     .area    _CODE
  286.  
  287. .div::
  288. .mod::
  289.     PUSH    HL
  290.     LD    HL,#.divsgn    ; Load HL with symbolic address
  291.     LD    (HL),#0x01
  292.     BIT    7,B        ; Is BC negative?
  293.     CALL    NZ,5$        ; Yes -> Negate it
  294.     BIT    7,D        ; Is DE negative?
  295.     CALL    NZ,7$        ; Yes -> Negate it
  296.     LD    HL,#.divtmp    ; Load HL with symbolic address
  297.     LD    (HL),C        ; Save the LS byte of the divisor
  298.     INC    HL
  299.     LD    (HL),B        ; Save the MS byte of the divisor
  300.     INC    HL
  301.     LD    (HL),#0x11    ; Save the divisor's bit count (decimal 17)
  302.     LD    BC,#0x00    ; BC will store the partial dividend
  303. 1$:
  304.     LD    HL,#.divcnt    ; Load HL with address of bit count (dec 17)
  305.     RL    E        ; Rotate the LSB into carry
  306.     RL    D        ; Rotate the MSB into carry
  307.     DEC    (HL)        ; Decrement the bit count
  308.     JR    Z,3$        ; Return if zero
  309.     RL    C        ; Rotate the MSB of the dividend into
  310.     RL    B        ;  the partial dividend stored in BC
  311.     DEC    HL        ; Point HL to divisor in memory
  312.     DEC    HL
  313.     LD    A,C        ; Get the LS byte of partial dividend
  314.     SUB    (HL)        ; Subtract the LS byte of the divisor
  315.     LD    C,A
  316.     INC    HL
  317.     LD    A,B        ; Get the MS byte of partial dividend
  318.     SBC    (HL)        ; Subtract with borrow the divisor
  319.     LD    B,A
  320.     JR    NC,2$        ; If carry=0, do not add divisor to
  321.                 ;  the result of previous subtraction
  322.     DEC    HL
  323.     LD    A,C        ; The divisor is larger than the partial
  324.     ADD    (HL)        ;  dividend, so the divisor must be
  325.     LD    C,A        ;  added to the result of the subtraction
  326.     INC    HL        ;  so that the previous value of the
  327.     LD    A,B        ;  partial dividend is re-established.
  328.     ADC    (HL)
  329.     LD    B,A
  330. 2$:
  331.     CCF            ; Complement the carry
  332.     JR    1$
  333. 3$:
  334.     LD    HL,#.divsgn    ; Load HL with symbolic address
  335.     XOR    A        ; A = 0
  336.     CP    (HL)        ; Was divisor xor dividend negative?
  337.     JR    NZ,4$        ; No
  338.     CALL    6$        ; Yes -> Negate results
  339.     CALL    8$
  340. 4$:
  341.     POP    HL
  342.     RET
  343.  
  344. 5$:
  345.     DEC    (HL)
  346. 6$:
  347.     LD    A,B
  348.     CPL
  349.     LD    B,A
  350.     LD    A,C
  351.     CPL
  352.     LD    C,A
  353.     INC    BC
  354.     RET
  355. 7$:
  356.     DEC    (HL)
  357. 8$:
  358.     LD    A,D
  359.     CPL
  360.     LD    D,A
  361.     LD    A,E
  362.     CPL
  363.     LD    E,A
  364.     INC    DE
  365.     RET
  366.  
  367. .divu::
  368. .modu::
  369.     PUSH    HL
  370.     LD    HL,#.divtmp    ; Load HL with symbolic address
  371.     LD    (HL),C        ; Save the LS byte of the divisor
  372.     INC    HL
  373.     LD    (HL),B        ; Save the MS byte of the divisor
  374.     INC    HL
  375.     LD    (HL),#0x11    ; Save the divisor's bit count (decimal 17)
  376.     LD    BC,#0x00    ; BC will store the partial dividend
  377. 1$:
  378.     LD    HL,#.divcnt    ; Load HL with address of bit count (dec 17)
  379.     RL    E        ; Rotate the LSB into carry
  380.     RL    D        ; Rotate the MSB into carry
  381.     DEC    (HL)        ; Decrement the bit count
  382.     JR    Z,3$        ; Return if zero
  383.     RL    C        ; Rotate the MSB of the dividend into
  384.     RL    B        ;  the partial dividend stored in BC
  385.     DEC    HL        ; Point HL to divisor in memory
  386.     DEC    HL
  387.     LD    A,C        ; Get the LS byte of partial dividend
  388.     SUB    (HL)        ; Subtract the LS byte of the divisor
  389.     LD    C,A
  390.     INC    HL
  391.     LD    A,B        ; Get the MS byte of partial dividend
  392.     SBC    (HL)        ; Subtract with borrow the divisor
  393.     LD    B,A
  394.     JR    NC,2$        ; If carry=0, do not add divisor to
  395.                 ;  the result of previous subtraction
  396.     DEC    HL
  397.     LD    A,C        ; The divisor is larger than the partial
  398.     ADD    (HL)        ;  dividend, so the divisor must be
  399.     LD    C,A        ;  added to the result of the subtraction
  400.     INC    HL        ;  so that the previous value of the
  401.     LD    A,B        ;  partial dividend is re-established.
  402.     ADC    (HL)
  403.     LD    B,A
  404. 2$:
  405.     CCF            ; Complement the carry
  406.     JR    1$
  407. 3$:
  408.     POP    HL
  409.     RET
  410.  
  411.     ; Call the initialization function for the mode specified in HL
  412. .set_mode:
  413.     LD    A,L
  414.     LD    (.mode),A
  415.  
  416.     LD    BC,#.MODE_TABLE
  417.     SLA    L        ; Multiply mode by 4
  418.     SLA    L
  419.     ADD    HL,BC
  420.     JP    (HL)        ; Jump to initialization routine
  421.  
  422.     ; Wait until all buttons have been released and debounced
  423. .padup:
  424.     PUSH    AF        ; Save modified registers
  425.     PUSH    BC
  426. 1$:
  427.     LD    B,#0xFF
  428. 2$:
  429.     CALL    .jpad
  430.     OR    A        ; Have all buttons been released ?
  431.     JR    NZ,1$        ; Not yet
  432.  
  433.     DEC    B
  434.     JR    NZ,2$
  435.     POP    BC        ; Restore registers
  436.     POP    AF
  437.     RET
  438.  
  439.     ; Get Keypad Button Status
  440.     ; The following bits are set if pressed:
  441.     ;   0x80 - Start   0x08 - Down
  442.     ;   0x40 - Select  0x04 - Up
  443.     ;   0x20 - B       0x02 - Left
  444.     ;   0x10 - A       0x01 - Right
  445. .jpad:
  446.     PUSH    BC        ; Save modified registers
  447.     LD    A,#0x20
  448.     LDH    (.JOYPAD),A    ; Turn on P15
  449.  
  450.     LDH    A,(.JOYPAD)    ; Delay
  451.     LDH    A,(.JOYPAD)
  452.     CPL
  453.     AND    #0x0F
  454.     SWAP    A
  455.     LD    B,A
  456.     LD    A,#0x10
  457.     LDH    (.JOYPAD),A    ; Turn on P14
  458.     LDH    A,(.JOYPAD)    ; Delay
  459.     LDH    A,(.JOYPAD)
  460.     LDH    A,(.JOYPAD)
  461.     LDH    A,(.JOYPAD)
  462.     LDH    A,(.JOYPAD)
  463.     LDH    A,(.JOYPAD)
  464.     CPL
  465.     AND    #0x0F
  466.     OR    B
  467.     SWAP    A
  468.     POP    BC        ; Restore registers
  469.     RET
  470.  
  471.     ; Wait for the key in B to be pressed
  472. .wait_pad:
  473. 1$:
  474.     CALL    .jpad        ; Hold startup screen until start is pressed
  475.     AND    B        ; Compare with mask ?
  476.     JR    Z,1$        ; No
  477.     RET
  478.  
  479.     ; Wait for VBL
  480. .wait_vbl:
  481.     LDH    A,(.LCDCONT)
  482.     ADD    A,A
  483.     RET    NC
  484.  
  485. 1$:
  486.     LDH    A,(.CURLINE)    ; 0xFF44 = LCD Y-Pos
  487.     CP    #0x90        ; 0x90 and bigger = in VBL
  488.     JR    NZ,1$        ; Loop until it $90
  489.     RET
  490.  
  491.     ; Wait for BC ns
  492. .delay_ns:
  493. 1$:
  494.     DEC    BC
  495.     LD    A,B
  496.     OR    C
  497.     JR    NZ,1$
  498.  
  499.     RET
  500.  
  501.     ; Wait for BC ms
  502. .delay_ms:
  503.     PUSH    DE
  504.     LD    DE,#00
  505. 1$:
  506.     DEC    DE
  507.     LD    A,D
  508.     OR    E
  509.     JR    NZ,1$
  510.     DEC    BC
  511.     LD    A,B
  512.     OR    C
  513.     JR    NZ,1$
  514.     POP    DE
  515.  
  516.     RET
  517.  
  518.     ; All colors to transparent
  519. .white:
  520.     XOR    A        ; A = 0
  521.     LDH    (.BGRDPAL),A
  522.     RET
  523.  
  524.     ; All colors to black
  525. .black:
  526.     LD    A,#0xFF
  527.     LDH    (.BGRDPAL),A
  528.     RET
  529.  
  530.     ; Sets the colors to normal palette
  531. .std_pal:
  532.     LD    A,#0b11100100    ; Grey 3 = 11 (Black)
  533.                 ; Grey 2 = 10 (Dark grey)
  534.                 ; Grey 1 = 01 (Light grey)
  535.                 ; Grey 0 = 00 (Transparent)
  536.     LDH    (.BGRDPAL),A
  537.     LDH    (.SPR0PAL),A
  538.     LD    A,#0b00011011
  539.     LDH    (.SPR1PAL),A
  540.     RET
  541.  
  542.     ; Initialize the tile set at HL with A
  543. .init_tiles:
  544.     LD    C,#0x10
  545.     LD    B,#0x00
  546. 1$:
  547.     LD    (HL+),A
  548.     DEC    B
  549.     JR    NZ,1$
  550.     DEC    C
  551.     JR    NZ,1$
  552.     RET
  553.  
  554.     ; Initialize part of the tile set from (BC) to (HL)
  555.     ; of size DE bytes
  556. .mv_tiles:
  557. 1$:
  558.     LDH    A,(.LCDSTAT)
  559.     AND    #0x02
  560.     JR    NZ,1$
  561.  
  562.     LD    A,(BC)
  563.     LD    (HL+),A
  564.     INC    BC
  565.     DEC    DE
  566.     LD    A,D
  567.     OR    E
  568.     JR    NZ,1$
  569.     RET
  570.  
  571.     ; Set background tile table to table starting at (BC)
  572. .set_btt:
  573.     LD    HL,#0x9800
  574.     JR    .set_tt
  575.  
  576.     ; Set window tile table to table starting at (BC)
  577. .set_wtt:
  578.     LD    HL,#0x9C00
  579.  
  580. .set_tt:
  581.     LD    DE,#0x0400    ; One whole GB Screen
  582.  
  583. 1$:
  584.     LDH    A,(.LCDSTAT)
  585.     AND    #0x02
  586.     JR    NZ,1$
  587.  
  588.     LD    A,(BC)
  589.     LD    (HL+),A
  590.     INC    BC
  591.     DEC    DE
  592.     LD    A,D
  593.     OR    E
  594.     JR    NZ,1$
  595.  
  596.     RET
  597.  
  598.     ; Set background tile table to B
  599. .init_btt:
  600.     LD    HL,#0x9800
  601.     JR    .init_tt
  602.  
  603.     ; Set window tile table to B
  604. .init_wtt:
  605.     LD    HL,#0x9C00
  606.  
  607. .init_tt:
  608.     LD    DE,#0x0400    ; One whole GB Screen
  609.  
  610. 1$:
  611.     LDH    A,(.LCDSTAT)
  612.     AND    #0x02
  613.     JR    NZ,1$
  614.  
  615.     LD    A,B
  616.     LD    (HL+),A
  617.  
  618.     DEC    DE
  619.     LD    A,D
  620.     OR    E
  621.     JR    NZ,1$
  622.  
  623.     RET
  624.  
  625.     ; Set background tile table from BC at xy = DE of size wh = HL
  626.     ; wh >= (1,1)
  627. .set_xy_btt:
  628.     PUSH    HL
  629.     LD    HL,#0x9800    ; Calculate origin
  630.     JR    .set_xy_tt
  631.  
  632.     ; Set window tile table from BC at xy = DE of size wh = HL
  633.     ; wh >= (1,1)
  634. .set_xy_wtt:
  635.     PUSH    HL
  636.     LD    HL,#0x9C00    ; Calculate origin
  637.  
  638. .set_xy_tt:
  639.     PUSH    BC
  640.     XOR    A        ; A = 0
  641.     OR    E
  642.     JR    Z,2$
  643.  
  644.     LD    BC,#0x20
  645. 1$:
  646.     ADD    HL,BC        ; y coordinate
  647.     DEC    E
  648.     JR    NZ,1$
  649. 2$:
  650.     LD    B,#0x00        ; x coordinate
  651.     LD    C,D
  652.     ADD    HL,BC
  653.  
  654.     POP    BC
  655.     POP    DE        ; DE = wh
  656.     PUSH    HL        ; Store origin
  657.     PUSH    DE        ; Store wh
  658. 3$:
  659.     LDH    A,(.LCDSTAT)
  660.     AND    #0x02
  661.     JR    NZ,3$
  662.  
  663.     LD    A,(BC)
  664.     LD    (HL+),A
  665.     INC    BC
  666.     DEC    D
  667.     JR    NZ,3$
  668.     POP    HL        ; Get wh
  669.     LD    D,H        ; Restore D = w
  670.     POP    HL        ; Get origin
  671.     DEC    E
  672.     JR    Z,4$
  673.  
  674.     PUSH    BC        ; Next line
  675.     LD    BC,#0x20
  676.     ADD    HL,BC
  677.     POP    BC
  678.  
  679.     PUSH    HL        ; Store current line
  680.     PUSH    DE        ; Store wh
  681.     JR    3$
  682. 4$:
  683.     RET
  684.  
  685.     ; Move sprite number C at xy = DE
  686. .mv_sprite:
  687.     LD    HL,#.OAM    ; Calculate origin of sprite info
  688.  
  689.     SLA    C        ; Multiply C by 4
  690.     SLA    C
  691.     LD    B,#0x00
  692.     ADD    HL,BC
  693.  
  694.     LD    A,E
  695.     LD    (HL+),A
  696.  
  697.     LD    A,D
  698.     LD    (HL+),A
  699.     RET
  700.  
  701.     ; Set sprite number C to tile D
  702. .set_sprite:
  703.     LD    HL,#.OAM    ; Calculate origin of sprite info
  704.  
  705.     SLA    C        ; Multiply C by 4
  706.     SLA    C
  707.     LD    B,#0x00
  708.     ADD    HL,BC
  709.     INC    HL        ; Add 2
  710.     INC    HL
  711.  
  712.     LD    A,D
  713.     LD    (HL),A
  714.     RET
  715.  
  716.     ; Set properties of sprite number C to D
  717. .prop_sprite:
  718.     LD    HL,#.OAM    ; Calculate origin of sprite info
  719.  
  720.     SLA    C        ; Multiply C by 4
  721.     SLA    C
  722.     LD    B,#0x00
  723.     ADD    HL,BC
  724.     INC    HL        ; Add 3
  725.     INC    HL
  726.     INC    HL
  727.  
  728.     LD    A,D
  729.     LD    (HL),A
  730.     RET
  731.  
  732.     ; Clear OAM data
  733. .clear_OAM:
  734.     LD    B,#0xA0        ; Clear OAM
  735.     LD    HL,#.OAM
  736.     XOR    A        ; A = 0
  737. 1$:
  738.     LD    (HL+),A
  739.     DEC    B
  740.     JR    NZ,1$
  741.     RET
  742.  
  743.     ; Copy OAM data to OAM RAM
  744. .start_refresh_OAM:
  745.     LD    A,#0xC0        ; OAM data address (0xC000)
  746.     LDH    (.DMA),A    ; Put A into DMA registers
  747.     LD    A,#0x28        ; We need to wait 160 ns
  748. 1$:
  749.     DEC    A
  750.     JR    NZ,1$
  751.     RET
  752. .end_refresh_OAM:
  753.  
  754. _mode::
  755.     LDA    HL,2(SP)
  756.     LD    L,(HL)
  757.     LD    H,#0x00
  758.     CALL    .set_mode
  759.     RET
  760.  
  761. _delay::
  762.     PUSH    BC
  763.     LDA    HL,4(SP)
  764.     LD    C,(HL)
  765.     INC    HL
  766.     LD    B,(HL)
  767.     CALL    .delay_ns
  768.     POP    BC
  769.     RET
  770.  
  771. _pause::
  772.     PUSH    BC
  773.     LDA    HL,4(SP)
  774.     LD    C,(HL)
  775.     INC    HL
  776.     LD    B,(HL)
  777.     CALL    .delay_ms
  778.     POP    BC
  779.     RET
  780.  
  781. _joypad::
  782.     CALL    .jpad
  783.     LD    H,#0x00        ; Return result in HL
  784.     LD    L,A
  785.     RET
  786.  
  787. _waitpad::
  788.     PUSH    BC
  789.     LDA    HL,4(SP)
  790.     LD    B,(HL)
  791.     CALL    .wait_pad
  792.     LD    H,#0x00        ; Return result in HL
  793.     LD    L,A
  794.     POP    BC
  795.     RET
  796.  
  797. _waitpadup::
  798.     CALL    .padup
  799.     RET
  800.  
  801. _enable_interrupts::
  802.     EI
  803.     RET
  804.  
  805. _disable_interrupts::
  806.     DI
  807.     RET
  808.  
  809. _display_on::
  810.     LDH    A,(.LCDCONT)
  811.     OR    #0x80
  812.     LDH    (.LCDCONT),A
  813.     RET
  814.  
  815. _display_off::
  816.     CALL    .wait_vbl    ; Must be in VBL before turning the screen off.
  817.     LDH    A,(.LCDCONT)
  818.     AND    #0xFF-0x80
  819.     LDH    (.LCDCONT),A
  820.     RET
  821.  
  822. _show_bkg::
  823.     LDH    A,(.LCDCONT)
  824.     OR    #0x01
  825.     LDH    (.LCDCONT),A
  826.     RET
  827.  
  828. _hide_bkg::
  829.     LDH    A,(.LCDCONT)
  830.     AND    #0xFF-0x01
  831.     LDH    (.LCDCONT),A
  832.     RET
  833.  
  834. _set_bkg_data::
  835.     PUSH    BC
  836.     PUSH    DE
  837.  
  838.     LDA    HL,11(SP)
  839.     LD    B,(HL)        ; data
  840.     DEC    HL
  841.     LD    C,(HL)
  842.     DEC    HL
  843.     LD    D,(HL)        ; nb_tiles
  844.     DEC    HL
  845.     LD    E,(HL)
  846.     DEC    HL
  847.     LD    A,(HL-)        ; first_tile
  848.     LD    L,(HL)
  849.     LD    H,A
  850.  
  851.     PUSH    HL
  852.     LD    H,D
  853.     LD    L,E
  854.     ADD    HL,HL        ; HL *= 16
  855.     ADD    HL,HL
  856.     ADD    HL,HL
  857.     ADD    HL,HL
  858.     LD    D,H
  859.     LD    E,L
  860.     POP    HL
  861.  
  862.     ADD    HL,HL        ; HL *= 16
  863.     ADD    HL,HL
  864.     ADD    HL,HL
  865.     ADD    HL,HL
  866.  
  867.     PUSH    BC
  868.     LD    BC,#0x9000
  869.     ADD    HL,BC
  870.     POP    BC
  871.  
  872.     CALL    .mv_tiles
  873.  
  874.     POP    DE
  875.     POP    BC
  876.     RET
  877.  
  878. _set_bkg_tiles::
  879.     PUSH    BC
  880.     PUSH    DE
  881.  
  882.     LDA    HL,6(SP)
  883.     LD    D,(HL)        ; x
  884.     INC    HL
  885.     INC    HL
  886.     LD    E,(HL)        ; y
  887.     LDA    HL,15(SP)
  888.     LD    B,(HL)        ; tilelist
  889.     DEC    HL
  890.     LD    C,(HL)
  891.     DEC    HL
  892.     DEC    HL
  893.     LD    A,(HL-)        ; h
  894.     DEC    HL
  895.     LD    H,(HL)        ; w
  896.     LD    L,A
  897.  
  898.     CALL    .set_xy_btt
  899.  
  900.     POP    DE
  901.     POP    BC
  902.     RET
  903.  
  904. _scroll_bkg::
  905.     LDA    HL,2(SP)
  906.     XOR    A        ; A = 0
  907.     CP    (HL)
  908.     JR    Z,1$
  909.  
  910.     LDH    A,(.SCROLLX)
  911.     ADD    (HL)
  912.     LDH    (.SCROLLX),A
  913. 1$:
  914.     INC    HL
  915.     INC    HL
  916.     XOR    A        ; A = 0
  917.     CP    (HL)
  918.     JR    Z,2$
  919.  
  920.     LDH    A,(.SCROLLY)
  921.     ADD    (HL)
  922.     LDH    (.SCROLLY),A
  923. 2$:
  924.     RET
  925.  
  926. _show_window::
  927.     LDH    A,(.LCDCONT)
  928.     OR    #0x20
  929.     LDH    (.LCDCONT),A
  930.     RET
  931.  
  932. _hide_window::
  933.     LDH    A,(.LCDCONT)
  934.     AND    #0xFF-0x20
  935.     LDH    (.LCDCONT),A
  936.     RET
  937.  
  938. _show_sprites::
  939.     LDH    A,(.LCDCONT)
  940.     OR    #0x02
  941.     LDH    (.LCDCONT),A
  942.     RET
  943.  
  944. _hide_sprites::
  945.     LDH    A,(.LCDCONT)
  946.     AND    #0xFF-0x02
  947.     LDH    (.LCDCONT),A
  948.     RET
  949.  
  950. _sprites8x8::
  951.     LDH    A,(.LCDCONT)
  952.     AND    #0xFF-0x04
  953.     LDH    (.LCDCONT),A
  954.     RET
  955.  
  956. _sprites8x16::
  957.     LDH    A,(.LCDCONT)
  958.     OR    #0x04
  959.     LDH    (.LCDCONT),A
  960.     RET
  961.  
  962. _set_sprite_data::
  963.     PUSH    BC
  964.     PUSH    DE
  965.  
  966.     LDA    HL,11(SP)
  967.     LD    B,(HL)        ; data
  968.     DEC    HL
  969.     LD    C,(HL)
  970.     DEC    HL
  971.     LD    D,(HL)        ; nb_tiles
  972.     DEC    HL
  973.     LD    E,(HL)
  974.     DEC    HL
  975.     LD    A,(HL-)        ; first_tile
  976.     LD    L,(HL)
  977.     LD    H,A
  978.  
  979.     PUSH    HL
  980.     LD    H,D
  981.     LD    L,E
  982.     ADD    HL,HL        ; HL *= 16
  983.     ADD    HL,HL
  984.     ADD    HL,HL
  985.     ADD    HL,HL
  986.     LD    D,H
  987.     LD    E,L
  988.     POP    HL
  989.  
  990.     ADD    HL,HL        ; HL *= 16
  991.     ADD    HL,HL
  992.     ADD    HL,HL
  993.     ADD    HL,HL
  994.  
  995.     PUSH    BC
  996.     LD    BC,#0x8000
  997.     ADD    HL,BC
  998.     POP    BC
  999.  
  1000.     CALL    .mv_tiles
  1001.  
  1002.     POP    DE
  1003.     POP    BC
  1004.     RET
  1005.  
  1006. _set_sprite_tile::
  1007.     PUSH    BC
  1008.     PUSH    DE
  1009.  
  1010.     LDA    HL,6(SP)
  1011.     LD    C,(HL)        ; nb
  1012.     INC    HL
  1013.     INC    HL
  1014.     LD    D,(HL)        ; tile
  1015.  
  1016.     CALL    .set_sprite
  1017.  
  1018.     POP    DE
  1019.     POP    BC
  1020.     RET
  1021.  
  1022. _set_sprite_prop::
  1023.     PUSH    BC
  1024.     PUSH    DE
  1025.  
  1026.     LDA    HL,6(SP)
  1027.     LD    C,(HL)        ; nb
  1028.     INC    HL
  1029.     INC    HL
  1030.     LD    D,(HL)        ; prop
  1031.  
  1032.     CALL    .prop_sprite
  1033.  
  1034.     POP    DE
  1035.     POP    BC
  1036.     RET
  1037.  
  1038. _move_sprite::
  1039.     PUSH    BC
  1040.     PUSH    DE
  1041.  
  1042.     LDA    HL,6(SP)
  1043.     LD    C,(HL)        ; nb
  1044.     INC    HL
  1045.     INC    HL
  1046.     LD    D,(HL)        ; x
  1047.     INC    HL
  1048.     INC    HL
  1049.     LD    E,(HL)        ; y
  1050.  
  1051.     CALL    .mv_sprite
  1052.  
  1053.     POP    DE
  1054.     POP    BC
  1055.     RET
  1056.